package handledb;

import javax.servlet.ServletRequestEvent;
import javax.servlet.http.HttpServletRequest;
import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class HandleDb implements JdbcTemplate {
    private DbPool dbPool;

    public HandleDb(DbPool dbPool) {
        this.dbPool = dbPool;
    }

    @Override
    public <E> E queryToObject(String sql, Class c, Object... params) {
        return dbPool.getPipeline().queryToObject(sql, dbPool.getClassInfo(c), params);
    }

    @Override
    public <E> E queryToObject(E e) {
        Class c = e.getClass();
        return dbPool.getPipeline().queryToObject(e, dbPool.getClassInfo(c));
    }

    @Override
    public <E> List<E> queryToList(String sql, Class c, Object... params) {
        return dbPool.getPipeline().queryToList(sql, dbPool.getClassInfo(c), params);
    }

    @Override
    public <E> List<E> queryToList(E obj) {
        return dbPool.getPipeline().queryToList(obj, dbPool.getClassInfo(obj.getClass()));
    }

    @Override
    public <E> List<E> queryToList(E e, int pageNo, int pageSize) {
        return dbPool.getPipeline().queryToList(e, dbPool.getClassInfo(e.getClass()), pageNo, pageSize);
    }

    @Override
    public String queryJson(String sql, Object... params) {
        return dbPool.getPipeline().queryToJson(sql, params);
    }

    @Override
    public String queryToJson(String sql, Class c, Object... params) {
        return dbPool.getPipeline().queryToJson(sql, dbPool.getClassInfo(c), params);
    }

    @Override
    public <T> String queryToJson(T t) {
        return dbPool.getPipeline().queryToJson(t, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public int updateBySql(String sql, Object... params) {
        return dbPool.getPipeline().updateBySql(sql, params);
    }

    @Override
    public <E> int update(E e) {
        return dbPool.getPipeline().update(e, dbPool.getClassInfo(e.getClass()));
    }

    @Override
    public <E> int delete(E e) {
        return dbPool.getPipeline().delete(e, dbPool.getClassInfo(e.getClass()));
    }

    @Override
    public <E> int create(E e) {
        return dbPool.getPipeline().create(e, dbPool.getClassInfo(e.getClass()));
    }

    @Override
    public <E> int countByObject(E e) {
        return dbPool.getPipeline().sumByObject(e, dbPool.getClassInfo(e.getClass()));
    }

    @Override
    public void close() {
        dbPool.closeCurrentPipeline();
    }

    @Override
    public void commitAndColse() {
        dbPool.commitAndCloseCurrentPipeline();
    }

    @Override
    public void rollbackAndColse() {
        dbPool.rollbackAndCloseCurrentPipeline();
    }

    @Override
    public ResultMap queryToMap(String sql, Object... params) {
        return dbPool.getPipeline().queryToMap(sql, params);
    }

    @Override
    public String queryToString(String sql, Object... params) {
        return dbPool.getPipeline().queryToString(sql, params);
    }

    @Override
    public List<String> queryToListStr(String sql, Object... params) {
        return dbPool.getPipeline().queryToListStr(sql, params);
    }

    @Override
    public int queryToInt(String sql, Object... params) {
        return dbPool.getPipeline().queryToInt(sql, params);
    }

    @Override
    public int countBySql(String sql, Object... params) {
        return dbPool.getPipeline().queryToInt("select count(*) from(" + sql + ") as page_query_count", params);
    }

    @Override
    public JdbcTemplate selectFields(String fields) {
        dbPool.getPipeline().selectFields = fields.split(",");
        return this;
    }

    @Override
    public JdbcTemplate unSelectFields(String fields) {
        dbPool.getPipeline().unSelectFields = fields.split(",");
        return this;
    }

    @Override
    public JdbcTemplate updateFields(String[] fields) {
        dbPool.getPipeline().updateFields = fields;
        return this;
    }

    @Override
    public JdbcTemplate updateFields(String fields) {
        if (fields != null) {
            dbPool.getPipeline().updateFields = fields.split(",");
        }
        return this;
    }

    @Override
    public JdbcTemplate notUpdateFields(String[] fields) {
        dbPool.getPipeline().notUpdateFields = fields;
        return this;
    }

    @Override
    public JdbcTemplate notUpdateFields(String fields) {
        if (fields != null) {
            dbPool.getPipeline().notUpdateFields = fields.split(",");
        }
        return this;
    }

    @Override
    public JdbcTemplate whereFields(String fields) {
        if (fields != null) {
            dbPool.getPipeline().whereFields = fields.split(",");
        }
        return this;
    }

    @Override
    public long openTransaction() {
        return dbPool.openTransaction();
    }

    @Override
    public long openTransaction(long failureTime) {
        return dbPool.openTransaction(failureTime);
    }

    @Override
    public long getValidTime(long transactionId) {
        return dbPool.getValidTime(transactionId);
    }

    @Override
    public void useTransaction(Long id) {
        dbPool.useTransaction(id);
    }

    @Override
    public void closeTransaction(Long id) {
        dbPool.closeTransaction(id);
    }

    @Override
    public void closeTransaction() {
        dbPool.closeTransaction();
    }

    @Override
    public <T> int templateUpdate(String tempSql, T t) {
        return dbPool.getPipeline().templateUpdate(tempSql, t, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public <T> T templateQueryOne(String tempSql, T t) {
        return dbPool.getPipeline().templateQueryOne(tempSql, t, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public <T, M> T templateQueryOne(String tempSql, M m, Class c) {
        return dbPool.getPipeline().templateQueryOne(tempSql, m, dbPool.getClassInfo(m.getClass()), dbPool.getClassInfo(c));
    }

    @Override
    public <T> List<T> templateQueryAll(String tempSql, T t) {
        return dbPool.getPipeline().templateQueryAll(tempSql, t, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public <T, M> List<T> templateQueryAll(String tempSql, M m, Class c) {
        return dbPool.getPipeline().templateQueryAll(tempSql, m, dbPool.getClassInfo(m.getClass()), dbPool.getClassInfo(c));
    }

    @Override
    public <T> List<T> templateQueryAll(String tempSql, T t, int pageNo, int pageSize) {
        return dbPool.getPipeline().templateQueryAll(tempSql, t, dbPool.getClassInfo(t.getClass()), pageNo, pageSize);
    }

    @Override
    public <T, M> List<T> templateQueryAll(String tempSql, M m, Class c, int pageNo, int pageSize) {
        return dbPool.getPipeline().templateQueryAll(tempSql, m, dbPool.getClassInfo(m.getClass()), dbPool.getClassInfo(c), pageNo, pageSize);
    }

    @Override
    public <T> int templateCount(String tempSql, T t) {
        return dbPool.getPipeline().templateCount(tempSql, t, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public <T> String templateResolver(String tempSql, T t, List<Object> params) {
        return dbPool.getPipeline().templateResolver(tempSql, t, params, dbPool.getClassInfo(t.getClass()));
    }

    @Override
    public Statement createStatement() throws SQLException {
        return dbPool.getPipeline().con.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return dbPool.getPipeline().con.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        return dbPool.getPipeline().con.nativeSQL(sql);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        dbPool.getPipeline().con.setAutoCommit(autoCommit);
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        return dbPool.getPipeline().con.getAutoCommit();
    }

    @Override
    public void commit() {
        try {
            dbPool.getPipeline().con.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void rollback() {
        try {
            dbPool.getPipeline().con.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void commitGlobal() throws SQLException {
        TransactionManage.dealGlobalTransaction(TransactionManage.COMMIT, null);
    }

    @Override
    public void rollbackGlobal() throws SQLException {
        TransactionManage.dealGlobalTransaction(TransactionManage.ROLLBACK,null);
    }

    @Override
    public boolean isClosed() throws SQLException {
        return dbPool.getPipeline().con.isClosed();
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return dbPool.getPipeline().con.getMetaData();
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        dbPool.getPipeline().con.setReadOnly(readOnly);
    }

    @Override
    public boolean isReadOnly() throws SQLException {
        return dbPool.getPipeline().con.isReadOnly();
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
        dbPool.getPipeline().con.setCatalog(catalog);
    }

    @Override
    public String getCatalog() throws SQLException {
        return dbPool.getPipeline().con.getCatalog();
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        dbPool.getPipeline().con.setTransactionIsolation(level);
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        return dbPool.getPipeline().con.getTransactionIsolation();
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        return dbPool.getPipeline().con.getWarnings();
    }

    @Override
    public void clearWarnings() throws SQLException {
        dbPool.getPipeline().con.clearWarnings();
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        return dbPool.getPipeline().con.createStatement(resultSetType, resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return dbPool.getPipeline().con.prepareCall(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return dbPool.getPipeline().con.getTypeMap();
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        dbPool.getPipeline().con.setTypeMap(map);
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
        dbPool.getPipeline().con.setHoldability(holdability);
    }

    @Override
    public int getHoldability() throws SQLException {
        return getHoldability();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        return dbPool.getPipeline().con.setSavepoint();
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return dbPool.getPipeline().con.setSavepoint(name);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        dbPool.getPipeline().con.rollback(savepoint);
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        dbPool.getPipeline().con.releaseSavepoint(savepoint);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return dbPool.getPipeline().con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return dbPool.getPipeline().con.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql, autoGeneratedKeys);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql, columnIndexes);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        return dbPool.getPipeline().con.prepareStatement(sql, columnNames);
    }

    @Override
    public Clob createClob() throws SQLException {
        return dbPool.getPipeline().con.createClob();
    }

    @Override
    public Blob createBlob() throws SQLException {
        return dbPool.getPipeline().con.createBlob();
    }

    @Override
    public NClob createNClob() throws SQLException {
        return dbPool.getPipeline().con.createNClob();
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        return dbPool.getPipeline().con.createSQLXML();
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        return dbPool.getPipeline().con.isValid(timeout);
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
        dbPool.getPipeline().con.setClientInfo(name, value);
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
        dbPool.getPipeline().con.setClientInfo(properties);
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        return dbPool.getPipeline().con.getClientInfo(name);
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        return dbPool.getPipeline().con.getClientInfo();
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        return dbPool.getPipeline().con.createArrayOf(typeName, elements);
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        return dbPool.getPipeline().con.createStruct(typeName, attributes);
    }

    @Override
    public void setSchema(String schema) throws SQLException {
        dbPool.getPipeline().con.setSchema(schema);
    }

    @Override
    public String getSchema() throws SQLException {
        return dbPool.getPipeline().con.getSchema();
    }

    @Override
    public void abort(Executor executor) throws SQLException {
        dbPool.getPipeline().con.abort(executor);
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
        dbPool.getPipeline().con.setNetworkTimeout(executor, milliseconds);
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        return dbPool.getPipeline().con.getNetworkTimeout();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return dbPool.getPipeline().con.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return dbPool.getPipeline().con.isWrapperFor(iface);
    }

    @Override
    public <E> JdbcTemplate fieldHasEmpty(E obj, String fieldNames) {
        if (obj == null) {
            throw new RuntimeException("the incoming parameter is null!");
        } else if (fieldNames != null && fieldNames.length() > 0) {
            ClassInfo classInfo = dbPool.getClassInfo(obj.getClass());
            String[] fields = fieldNames.split(",");
            int i = 0;
            try {
                for (String item : fields) {
                    i = 0;
                    for (FieldInfo info : classInfo.allFieldInfos) {
                        if (info.name.equals(item) && info.field.get(obj) == null) {
                            throw new RuntimeException("field[".concat(item).concat("] is not null!"));
                        }
                        i += 1;
                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return this;
    }
}
